/**
 * @file operator_desc.cpp
 *
 * Copyright (C) 2023-2024. Huawei Technologies Co., Ltd. All rights reserved.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
#include "operator_desc.h"

#include "common.h"

using namespace std;

OperatorDesc::OperatorDesc() {}

OperatorDesc::OperatorDesc(const OperatorDesc& other)
{
    INFO_LOG("OperatorDesc::OperatorDesc COPY CONSTRUCTOR (other.inputDesc.size=%zu, other.outputDesc.size=%zu)",
             other.inputDesc.size(), other.outputDesc.size());

    // 深拷贝 opType
    opType = other.opType;

    // 深拷贝 inputDesc
    for (auto* desc : other.inputDesc) {
        if (desc != nullptr) {
            // 获取原始张量描述符的信息
            aclDataType dataType = aclGetTensorDescType(desc);
            int numDims = aclGetTensorDescNumDims(desc);
            aclFormat format = aclGetTensorDescFormat(desc);
            
            // 获取形状信息
            std::vector<int64_t> dims(numDims);
            for (int i = 0; i < numDims; ++i) {
                int64_t dimSize;
                if (aclGetTensorDescDimV2(desc, i, &dimSize) == ACL_SUCCESS) {
                    dims[i] = dimSize;
                }
            }
            
            // 创建新的张量描述符
            aclTensorDesc* newDesc = aclCreateTensorDesc(dataType, numDims, dims.data(), format);
            if (newDesc != nullptr) {
                inputDesc.push_back(newDesc);
                INFO_LOG("OperatorDesc::OperatorDesc COPY: Created new input tensor desc=%p from original=%p",
                         newDesc, desc);
            } else {
                ERROR_LOG("OperatorDesc::OperatorDesc COPY: Failed to create input tensor desc");
            }
        }
    }

    // 深拷贝 outputDesc
    for (auto* desc : other.outputDesc) {
        if (desc != nullptr) {
            // 获取原始张量描述符的信息
            aclDataType dataType = aclGetTensorDescType(desc);
            int numDims = aclGetTensorDescNumDims(desc);
            aclFormat format = aclGetTensorDescFormat(desc);
            
            // 获取形状信息
            std::vector<int64_t> dims(numDims);
            for (int i = 0; i < numDims; ++i) {
                int64_t dimSize;
                if (aclGetTensorDescDimV2(desc, i, &dimSize) == ACL_SUCCESS) {
                    dims[i] = dimSize;
                }
            }
            
            // 创建新的张量描述符
            aclTensorDesc* newDesc = aclCreateTensorDesc(dataType, numDims, dims.data(), format);
            if (newDesc != nullptr) {
                outputDesc.push_back(newDesc);
                INFO_LOG("OperatorDesc::OperatorDesc COPY: Created new output tensor desc=%p from original=%p",
                         newDesc, desc);
            } else {
                ERROR_LOG("OperatorDesc::OperatorDesc COPY: Failed to create output tensor desc");
            }
        }
    }

    INFO_LOG("OperatorDesc::OperatorDesc COPY CONSTRUCTOR completed (inputDesc.size=%zu, outputDesc.size=%zu)",
             inputDesc.size(), outputDesc.size());
}

OperatorDesc& OperatorDesc::operator=(const OperatorDesc& other)
{
    INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT (this.inputDesc.size=%zu, other.inputDesc.size=%zu)",
             inputDesc.size(), other.inputDesc.size());

    if (this == &other) {
        INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT: self assignment, skip");
        return *this;
    }

    // 清理当前对象的资源
    for (auto* desc : inputDesc) {
        if (desc != nullptr) {
            INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT: Destroying old input tensor desc=%p", desc);
            aclDestroyTensorDesc(desc);
        }
    }
    inputDesc.clear();

    for (auto* desc : outputDesc) {
        if (desc != nullptr) {
            INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT: Destroying old output tensor desc=%p", desc);
            aclDestroyTensorDesc(desc);
        }
    }
    outputDesc.clear();

    // 深拷贝 opType
    opType = other.opType;

    // 深拷贝 inputDesc
    for (auto* desc : other.inputDesc) {
        if (desc != nullptr) {
            // 获取原始张量描述符的信息
            aclDataType dataType = aclGetTensorDescType(desc);
            int numDims = aclGetTensorDescNumDims(desc);
            aclFormat format = aclGetTensorDescFormat(desc);
            
            // 获取形状信息
            std::vector<int64_t> dims(numDims);
            for (int i = 0; i < numDims; ++i) {
                int64_t dimSize;
                if (aclGetTensorDescDimV2(desc, i, &dimSize) == ACL_SUCCESS) {
                    dims[i] = dimSize;
                }
            }
            
            // 创建新的张量描述符
            aclTensorDesc* newDesc = aclCreateTensorDesc(dataType, numDims, dims.data(), format);
            if (newDesc != nullptr) {
                inputDesc.push_back(newDesc);
                INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT: Created new input tensor desc=%p from original=%p",
                         newDesc, desc);
            } else {
                ERROR_LOG("OperatorDesc::operator= COPY ASSIGNMENT: Failed to create input tensor desc");
            }
        }
    }

    // 深拷贝 outputDesc
    for (auto* desc : other.outputDesc) {
        if (desc != nullptr) {
            // 获取原始张量描述符的信息
            aclDataType dataType = aclGetTensorDescType(desc);
            int numDims = aclGetTensorDescNumDims(desc);
            aclFormat format = aclGetTensorDescFormat(desc);
            
            // 获取形状信息
            std::vector<int64_t> dims(numDims);
            for (int i = 0; i < numDims; ++i) {
                int64_t dimSize;
                if (aclGetTensorDescDimV2(desc, i, &dimSize) == ACL_SUCCESS) {
                    dims[i] = dimSize;
                }
            }
            
            // 创建新的张量描述符
            aclTensorDesc* newDesc = aclCreateTensorDesc(dataType, numDims, dims.data(), format);
            if (newDesc != nullptr) {
                outputDesc.push_back(newDesc);
                INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT: Created new output tensor desc=%p from original=%p",
                         newDesc, desc);
            } else {
                ERROR_LOG("OperatorDesc::operator= COPY ASSIGNMENT: Failed to create output tensor desc");
            }
        }
    }

    INFO_LOG("OperatorDesc::operator= COPY ASSIGNMENT completed (inputDesc.size=%zu, outputDesc.size=%zu)",
             inputDesc.size(), outputDesc.size());
    return *this;
}

OperatorDesc::OperatorDesc(OperatorDesc&& other) noexcept
    : opType(std::move(other.opType)),
      inputDesc(std::move(other.inputDesc)),
      outputDesc(std::move(other.outputDesc))
{
    INFO_LOG("OperatorDesc::OperatorDesc MOVE CONSTRUCTOR (moved inputDesc.size=%zu, outputDesc.size=%zu)",
             inputDesc.size(), outputDesc.size());
    
    // 清空源对象，防止双重释放
    other.inputDesc.clear();
    other.outputDesc.clear();
}

OperatorDesc& OperatorDesc::operator=(OperatorDesc&& other) noexcept
{
    INFO_LOG("OperatorDesc::operator= MOVE ASSIGNMENT (this.inputDesc.size=%zu, other.inputDesc.size=%zu)",
             inputDesc.size(), other.inputDesc.size());

    if (this == &other) {
        INFO_LOG("OperatorDesc::operator= MOVE ASSIGNMENT: self assignment, skip");
        return *this;
    }

    // 清理当前对象的资源
    for (auto* desc : inputDesc) {
        if (desc != nullptr) {
            INFO_LOG("OperatorDesc::operator= MOVE ASSIGNMENT: Destroying old input tensor desc=%p", desc);
            aclDestroyTensorDesc(desc);
        }
    }
    inputDesc.clear();

    for (auto* desc : outputDesc) {
        if (desc != nullptr) {
            INFO_LOG("OperatorDesc::operator= MOVE ASSIGNMENT: Destroying old output tensor desc=%p", desc);
            aclDestroyTensorDesc(desc);
        }
    }
    outputDesc.clear();

    // 移动资源
    opType = std::move(other.opType);
    inputDesc = std::move(other.inputDesc);
    outputDesc = std::move(other.outputDesc);

    // 清空源对象，防止双重释放
    other.inputDesc.clear();
    other.outputDesc.clear();

    INFO_LOG("OperatorDesc::operator= MOVE ASSIGNMENT completed (inputDesc.size=%zu, outputDesc.size=%zu)",
             inputDesc.size(), outputDesc.size());
    return *this;
}

OperatorDesc::~OperatorDesc()
{
    INFO_LOG("OperatorDesc::~OperatorDesc ENTER (inputDesc.size=%zu, outputDesc.size=%zu)",
             inputDesc.size(), outputDesc.size());

    for (auto *desc : inputDesc) {
        if (desc != nullptr) {
            INFO_LOG("OperatorDesc::~OperatorDesc: Destroying input tensor desc=%p", desc);
            aclDestroyTensorDesc(desc);
        } else {
            INFO_LOG("OperatorDesc::~OperatorDesc: input tensor desc is nullptr, skip destroy");
        }
    }

    for (auto *desc : outputDesc) {
        if (desc != nullptr) {
            INFO_LOG("OperatorDesc::~OperatorDesc: Destroying output tensor desc=%p", desc);
            aclDestroyTensorDesc(desc);
        } else {
            INFO_LOG("OperatorDesc::~OperatorDesc: output tensor desc is nullptr, skip destroy");
        }
    }

    INFO_LOG("OperatorDesc::~OperatorDesc EXIT");
}

OperatorDesc &OperatorDesc::AddInputTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format)
{
    aclTensorDesc *desc = aclCreateTensorDesc(dataType, numDims, dims, format);
    if (desc == nullptr) {
        ERROR_LOG("create tensor failed");
        return *this;
    }  
    inputDesc.emplace_back(desc);
    return *this;
}

OperatorDesc &OperatorDesc::AddOutputTensorDesc(aclDataType dataType, int numDims, const int64_t *dims,
                                                aclFormat format)
{
    aclTensorDesc *desc = aclCreateTensorDesc(dataType, numDims, dims, format);
    if (desc == nullptr) {
        ERROR_LOG("create tensor failed");
        return *this;
    }

    outputDesc.emplace_back(desc);
    return *this;
}
